/*
 * Energy.java
 *
 * Copyright 2008 the Desert Labs Project (http://desertlabs.us)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package us.desertlabs.physics;

import java.math.BigDecimal;
import us.desertlabs.number.BigUtility;

/**
 * This is used to represent an amount of energy. Energy describes the
 * application of force over a distance.
 *
 * @author Brandon Franklin
 */
public class Energy extends SimpleUnit {

    private static final long serialVersionUID = 3616727184191140918L;

    /**
     * Given a <CODE>Force</CODE> and <CODE>Distance</CODE>, calculates and
     * returns the corresponding amount of <CODE>Energy</CODE>. Note that
     * <CODE>Force</CODE> is a <CODE>DimensionalValue</CODE> while <CODE>Distance</CODE>
     * is a <CODE>SimpleUnit</CODE>. The inconsistency is solved by
     * converting <CODE>Force</CODE> into an aggregate value.
     *
     * @param force the <CODE>Force</CODE> being applied
     * @param distance the <CODE>Distance</CODE> over which the <CODE>Force</CODE>
     *        is being applied
     * @return the <CODE>Energy</CODE> resulting from applying the <CODE>Force</CODE>
     *         over the supplied <CODE>Distance</CODE>
     * @throws IllegalArgumentException if either of the parameters is invalid
     *         for any reason
     */
    static public Energy calculate( final Force force, final Distance distance ) {

        // Validate the force
        if( force == null ) {
            throw new IllegalArgumentException( "Force cannot be null." );
        } else if( !force.isValid() ) {
            throw new IllegalArgumentException( "Force is internally invalid." );
        }

        // Validate the distance
        if( distance == null ) {
            throw new IllegalArgumentException( "Distance cannot be null." );
        }

        // Do the calculation
        final BigDecimal bigDecDist = new BigDecimal( distance.toString() );
        final BigDecimal bigDecForce = new BigDecimal( force.getAggregateValue().toString() );
        final BigDecimal result = BigUtility.clipScale( bigDecForce.multiply( bigDecDist ) );

        return new Energy( result );
    }

    /**
     * Creates a new instance of <CODE>Energy</CODE> representing the
     * specified amount of energy.
     *
     * @param amount the amount of energy to be represented
     * @throws IllegalArgumentException if the parameter is invalid for any
     *         reason
     */
    public Energy( final Number amount ) {
        super( amount );
    }
}
